// This is a simple example of lighting.  A sphere is drawn at the origin.  
// The controls allow you to move the position of the light source, the properties 
// of the light, and the properties of the surface material.



import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.*;
import java.awt.*;
import javax.swing.*;

import java.awt.event.*;
import javax.swing.event.*;



public class Sphere implements GLEventListener, ActionListener, ChangeListener {
	
	public static void main(String[] args) {
		new Sphere();
	}
	
	private int INITIAL_WIDTH=800;
	private int INITIAL_HEIGHT=800;
	
	JButton quitButton;
	JButton lightPosButton, lightAmbientButton, lightDiffuseButton, lightSpecularButton;
	JButton materialAmbientButton, materialDiffuseButton, materialSpecularButton, materialShininessButton;
	private GLCanvas canvas;
	private GL2 gl;
	private GLU glu;
	
	private JSlider lightXSlider, lightYSlider, lightZSlider;
	private JSlider lightAmbientRSlider, lightAmbientGSlider, lightAmbientBSlider;
	private JSlider lightDiffuseRSlider, lightDiffuseGSlider, lightDiffuseBSlider;
	private JSlider lightSpecularRSlider, lightSpecularGSlider, lightSpecularBSlider;
	private JSlider materialAmbientRSlider, materialAmbientGSlider, materialAmbientBSlider;
	private JSlider materialDiffuseRSlider, materialDiffuseGSlider, materialDiffuseBSlider;
	private JSlider materialSpecularRSlider, materialSpecularGSlider, materialSpecularBSlider;
	private JSlider materialShininessSlider;
	
	private JFrame lightPosFrame, lightAmbientFrame, lightDiffuseFrame, lightSpecularFrame;
	private JFrame materialAmbientFrame, materialDiffuseFrame, materialSpecularFrame, materialShininessFrame;
	
	private boolean lightPosVisible =false;
	private boolean lightAmbientVisible = false;
	private boolean lightDiffuseVisible = false;
	private boolean lightSpecularVisible = false;
	private boolean materialAmbientVisible = false;
	private boolean materialDiffuseVisible = false;
	private boolean materialSpecularVisible = false;
	private boolean materialShininessVisible = false;
		
	private float lightAmbient[] = {0f, 0f, 0f, 1f};
	private float lightDiffuse[] = {1f, 1f, 1f, 1f};
	private float lightSpecular[] = {1f, 1f, 1f, 1f};
	
	private float lightPosition[] = {50, 0, 0, 1};
	
	private float materialAmbient[] = {0.2f, 0f, 0f};
	private float materialDiffuse[] = {0.5f, 0.5f, 0.5f};
	private float materialSpecular[] = {0.1f, 0.1f, 0.1f};
	
	private int materialShininess = 100;
	
	// The viewer is at (2, 0, 0); this doesn't change.
	private float viewerX = 50f;
	private float viewerY  = 0f;
	private float viewerZ = 0f;
	
	private GLUquadric quad;

	public  Sphere() {
			GLProfile glp=GLProfile.getDefault();
			GLCapabilities caps = new GLCapabilities(glp);
			canvas = new GLCanvas(caps);
			JFrame frame = new JFrame("SPHERE");

			frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
			frame.setLayout(new BorderLayout());
			JPanel north = new JPanel( new BorderLayout());
			
			JPanel firstMainRow = new JPanel( new FlowLayout(FlowLayout.LEADING));
			
			quitButton = new JButton( "Quit");
			quitButton.addActionListener(this);
			firstMainRow.add(quitButton);
			north.add(firstMainRow, BorderLayout.NORTH);
			
			JPanel secondMainRow = new JPanel( new FlowLayout(FlowLayout.LEADING));
			secondMainRow.add(new JLabel("Light: "));
			lightPosButton = new JButton( "Position");
			lightPosButton.addActionListener(this);
			secondMainRow.add(lightPosButton);
			lightAmbientButton = new JButton( "Ambient");
			lightAmbientButton.addActionListener(this);
			secondMainRow.add(lightAmbientButton);
			lightDiffuseButton = new JButton( "Diffuse");
			lightDiffuseButton.addActionListener(this);
			secondMainRow.add(lightDiffuseButton);
			lightSpecularButton = new JButton( "Specular");
			lightSpecularButton.addActionListener(this);
			secondMainRow.add(lightSpecularButton);
			north.add(secondMainRow, BorderLayout.CENTER);

			JPanel thirdMainRow = new JPanel( new FlowLayout(FlowLayout.LEADING));
			thirdMainRow.add(new JLabel("Material: "));
			materialAmbientButton = new JButton( "Ambient");
			materialAmbientButton.addActionListener(this);
			thirdMainRow.add(materialAmbientButton);
			materialDiffuseButton = new JButton( "Diffuse");
			materialDiffuseButton.addActionListener(this);
			thirdMainRow.add(materialDiffuseButton);
			materialSpecularButton = new JButton( "Specular");
			materialSpecularButton.addActionListener(this);
			thirdMainRow.add(materialSpecularButton);
			materialShininessButton = new JButton( "Shininess");
			materialShininessButton.addActionListener(this);
			thirdMainRow.add(materialShininessButton);
			north.add(thirdMainRow, BorderLayout.SOUTH);
			frame.add(north, BorderLayout.NORTH);
			
			lightPosFrame = new JFrame("Light Position");
			lightPosFrame.setSize(600, 300);
			lightPosFrame.setLayout(new GridLayout(3, 1));
			lightPosFrame.setVisible(false);	
			lightPosFrame.setAlwaysOnTop(true);
			lightPosFrame.setLocation(800, 50);

			JPanel row1 = new JPanel(new BorderLayout());
			lightXSlider = newSlider(row1, -100, 100, 25, "   X");
			lightXSlider.setValue( (int)(lightPosition[0]));
			lightPosFrame.add(row1);
			JPanel row2 = new JPanel(new BorderLayout());
			lightYSlider = newSlider(row2, -100, 100, 25, "   Y");
			lightYSlider.setValue( (int)(lightPosition[1]));
			lightPosFrame.add(row2);
			JPanel row3 = new JPanel(new BorderLayout());
			lightZSlider = newSlider(row3, -100, 100, 25, "   Z");
			lightZSlider.setValue( (int)(lightPosition[2]));
			lightPosFrame.add(row3);

			lightAmbientFrame = new JFrame("Light Ambient");
			lightAmbientFrame.setSize(600, 300);
			lightAmbientFrame.setLayout(new GridLayout(3, 1));
			lightAmbientFrame.setVisible(false);	
			lightAmbientFrame.setAlwaysOnTop(true);
			lightAmbientFrame.setLocation(800, 50);
			
			JPanel row4 = new JPanel(new BorderLayout());
			lightAmbientRSlider = newSlider(row4, 0, 100, 10, " Red");
			lightAmbientRSlider.setValue( (int)(100*lightAmbient[0]));
			lightAmbientFrame.add(row4);
			JPanel row5 = new JPanel(new BorderLayout());
			lightAmbientGSlider = newSlider(row5, 0, 100, 10, " Green");
			lightAmbientGSlider.setValue( (int)(100*lightAmbient[1]));
			lightAmbientFrame.add(row5);
			JPanel row6 = new JPanel(new BorderLayout());
			lightAmbientBSlider = newSlider(row6, 0, 100, 10, " Blue");
			lightAmbientBSlider.setValue( (int)(100*lightAmbient[2]));
			lightAmbientFrame.add(row6);

			lightDiffuseFrame = new JFrame("Light Diffuse");
			lightDiffuseFrame.setSize(600, 300);
			lightDiffuseFrame.setLayout(new GridLayout(3, 1));
			lightDiffuseFrame.setVisible(false);	
			lightDiffuseFrame.setAlwaysOnTop(true);
			lightDiffuseFrame.setLocation(800, 50);
			
			JPanel row7 = new JPanel(new BorderLayout());
			lightDiffuseRSlider = newSlider(row7, 0, 100, 10, " Red");
			lightDiffuseRSlider.setValue( (int)(100*lightDiffuse[0]));
			lightDiffuseFrame.add(row7);
			JPanel row8 = new JPanel(new BorderLayout());
			lightDiffuseGSlider = newSlider(row8, 0, 100, 10, " Green");
			lightDiffuseGSlider.setValue( (int)(100*lightDiffuse[1]));
			lightDiffuseFrame.add(row8);
			JPanel row9 = new JPanel(new BorderLayout());
			lightDiffuseBSlider = newSlider(row9, 0, 100, 10, " Blue");
			lightDiffuseBSlider.setValue( (int)(100*lightDiffuse[2]));
			lightDiffuseFrame.add(row9);
			
			lightSpecularFrame = new JFrame("Light Specular");
			lightSpecularFrame.setSize(600, 300);
			lightSpecularFrame.setLayout(new GridLayout(3, 1));
			lightSpecularFrame.setVisible(false);	
			lightSpecularFrame.setAlwaysOnTop(true);
			lightSpecularFrame.setLocation(800, 50);
			
			JPanel row10 = new JPanel(new BorderLayout());
			lightSpecularRSlider = newSlider(row10, 0, 100, 10, " Red");
			lightSpecularRSlider.setValue( (int)(100*lightSpecular[0]));
			lightSpecularFrame.add(row10);
			JPanel row11 = new JPanel(new BorderLayout());
			lightSpecularGSlider = newSlider(row11, 0, 100, 10, " Green");
			lightSpecularGSlider.setValue( (int)(100*lightSpecular[1]));
			lightSpecularFrame.add(row11);
			JPanel row12 = new JPanel(new BorderLayout());
			lightSpecularBSlider = newSlider(row12, 0, 100, 10, " Blue");
			lightSpecularBSlider.setValue( (int)(100*lightSpecular[2]));
			lightSpecularFrame.add(row12); 

			materialAmbientFrame = new JFrame( "Material Ambient");	
			materialAmbientFrame.setSize(600, 300);
			materialAmbientFrame.setLayout(new GridLayout(3, 1));
			materialAmbientFrame.setVisible(false);	
			materialAmbientFrame.setAlwaysOnTop(true);
			materialAmbientFrame.setLocation(800, 50);
			
			JPanel row13 = new JPanel(new BorderLayout());
			materialAmbientRSlider = newSlider(row13, 0, 100, 10, " Red");
			materialAmbientRSlider.setValue( (int)(100*materialAmbient[0]));
			materialAmbientFrame.add(row13);
			JPanel row14 = new JPanel(new BorderLayout());
			materialAmbientGSlider = newSlider(row14, 0, 100, 10, " Green");
			materialAmbientGSlider.setValue( (int)(100*materialAmbient[1]));
			materialAmbientFrame.add(row14);
			JPanel row15 = new JPanel(new BorderLayout());
			materialAmbientBSlider = newSlider(row15, 0, 100, 10, " Blue");
			materialAmbientBSlider.setValue( (int)(100*materialAmbient[2]));
			materialAmbientFrame.add(row15);

			materialDiffuseFrame = new JFrame("Material Diffuse");
			materialDiffuseFrame.setSize(600, 300);
			materialDiffuseFrame.setLayout(new GridLayout(3, 1));
			materialDiffuseFrame.setVisible(false);	
			materialDiffuseFrame.setAlwaysOnTop(true);
			materialDiffuseFrame.setLocation(800, 50);
			
			JPanel row16 = new JPanel(new BorderLayout());
			materialDiffuseRSlider = newSlider(row16, 0, 100, 10, " Red");
			materialDiffuseRSlider.setValue( (int)(100*materialDiffuse[0]));
			materialDiffuseFrame.add(row16);
			JPanel row17 = new JPanel(new BorderLayout());
			materialDiffuseGSlider = newSlider(row17, 0, 100, 10, " Green");
			materialDiffuseGSlider.setValue( (int)(100*materialDiffuse[1]));
			materialDiffuseFrame.add(row17);
			JPanel row18 = new JPanel(new BorderLayout());
			materialDiffuseBSlider = newSlider(row18, 0, 100, 10, " Blue");
			materialDiffuseBSlider.setValue( (int)(100*materialDiffuse[2]));
			materialDiffuseFrame.add(row18); 

			materialSpecularFrame = new JFrame("Material Specular");
			materialSpecularFrame.setSize(600, 300);
			materialSpecularFrame.setLayout(new GridLayout(3, 1));
			materialSpecularFrame.setVisible(false);	
			materialSpecularFrame.setAlwaysOnTop(true);
			materialSpecularFrame.setLocation(800, 50);
			
			JPanel row19 = new JPanel(new BorderLayout());
			materialSpecularRSlider = newSlider(row19, 0, 100, 10, " Red");
			materialSpecularRSlider.setValue( (int)(100*materialSpecular[0]));
			materialSpecularFrame.add(row19); 
			JPanel row20 = new JPanel(new BorderLayout());
			materialSpecularGSlider = newSlider(row20, 0, 100, 10, " Green");
			materialSpecularGSlider.setValue( (int)(100*materialSpecular[1]));
			materialSpecularFrame.add(row20);
			JPanel row21 = new JPanel(new BorderLayout());
			materialSpecularBSlider = newSlider(row21, 0, 100, 10, " Blue");
			materialSpecularBSlider.setValue( (int)(100*materialSpecular[2]));
			materialSpecularFrame.add(row21); 

			materialShininessFrame = new JFrame("Material Shininess");
			materialShininessFrame.setSize(600, 300);
			materialShininessFrame.setVisible(false);	
			materialShininessFrame.setAlwaysOnTop(true);
			materialShininessFrame.setLocation(800, 50);
			
			JPanel row22 = new JPanel(new BorderLayout());
			materialShininessSlider = newSlider(row22, 0, 150, 25, " Shininess");
			materialShininessSlider.setValue( (int)(materialShininess) );
			materialShininessFrame.add(row22); 
			
			JPanel myCanvas = new JPanel(new GridLayout(1,1));
			myCanvas.add(canvas);
			frame.add(myCanvas, BorderLayout.CENTER);
			
			frame.setVisible(true);
			canvas.addGLEventListener(this);

			FPSAnimator animator = new FPSAnimator(canvas, 60);
			animator.start(); 
			
	}
	
	// This assumes the parent is a panel using BorderLayout.
	JSlider newSlider(JPanel parent, int min, int max, int step, String label) {
		JSlider S = new JSlider(min, max);
		S.setMajorTickSpacing(step);
		S.setPaintTicks(true);
		S.setPaintLabels(true); 
		S.addChangeListener(this);
		JLabel name = new JLabel(label);
		parent.add(name, BorderLayout.WEST); 
		parent.add(S, BorderLayout.CENTER);
		return S;
	}
	
	public void actionPerformed(ActionEvent event) {
			if (event.getSource() == quitButton)
				System.exit(0);
			else if (event.getSource() == lightPosButton) {
				lightPosVisible = !lightPosVisible;
				lightPosFrame.setVisible(lightPosVisible);
			}
			else if (event.getSource() == lightAmbientButton) {
				lightAmbientVisible = !lightAmbientVisible;
				lightAmbientFrame.setVisible(lightAmbientVisible);
			}
			else if (event.getSource() == lightDiffuseButton) {
				lightDiffuseVisible = !lightDiffuseVisible;
				lightDiffuseFrame.setVisible(lightDiffuseVisible);
			}
			else if (event.getSource() == lightSpecularButton) {
				lightSpecularVisible = !lightSpecularVisible;
				lightSpecularFrame.setVisible(lightSpecularVisible);
			}
			else if (event.getSource() == materialAmbientButton) {
				materialAmbientVisible = !materialAmbientVisible;
				materialAmbientFrame.setVisible(materialAmbientVisible);
			}
			else if (event.getSource() == materialDiffuseButton) {
				materialDiffuseVisible = !materialDiffuseVisible;
				materialDiffuseFrame.setVisible(materialDiffuseVisible);
			}
			else if (event.getSource() == materialSpecularButton) {
				materialSpecularVisible = !materialSpecularVisible;
				materialSpecularFrame.setVisible(materialSpecularVisible);
			}
			else if (event.getSource() == materialShininessButton) {
				materialShininessVisible = !materialShininessVisible;
				materialShininessFrame.setVisible(materialShininessVisible);
			}
	}
	
	public void stateChanged(ChangeEvent e) {
		if (e.getSource() == lightXSlider) {
			lightPosition[0] = lightXSlider.getValue();
		}
		else if (e.getSource() == lightYSlider) {
			lightPosition[1] = lightYSlider.getValue();
		}
		else if (e.getSource() == lightZSlider) {
			lightPosition[2] = lightZSlider.getValue();
		}
		else if (e.getSource() == lightAmbientRSlider) {
			lightAmbient[0] = lightAmbientRSlider.getValue()/100f;
		}
		else if (e.getSource() == lightAmbientGSlider) {
			lightAmbient[1] = lightAmbientGSlider.getValue()/100f;
		}
		else if (e.getSource() == lightAmbientBSlider) {
			lightAmbient[2] = lightAmbientBSlider.getValue()/100f;
		}
		else if (e.getSource() == lightDiffuseRSlider) {
			lightDiffuse[0] = lightDiffuseRSlider.getValue()/100f;
		}
		else if (e.getSource() == lightDiffuseGSlider) {
			lightDiffuse[1] = lightDiffuseGSlider.getValue()/100f;
		}
		else if (e.getSource() == lightDiffuseBSlider) {
			lightDiffuse[2] = lightDiffuseBSlider.getValue()/100f;
		}
		else if (e.getSource() == lightSpecularRSlider) {
			lightSpecular[0] = lightSpecularRSlider.getValue()/100f;
		}
		else if (e.getSource() == lightSpecularGSlider) {
			lightSpecular[1] = lightSpecularGSlider.getValue()/100f;
		}
		else if (e.getSource() == lightSpecularBSlider) {
			lightSpecular[2] = lightSpecularBSlider.getValue()/100f;
		}
		else if (e.getSource() == materialAmbientRSlider) {
			materialAmbient[0] = materialAmbientRSlider.getValue()/100f;
		}
		else if (e.getSource() == materialAmbientGSlider) {
			materialAmbient[1] = materialAmbientGSlider.getValue()/100f;
		}
		else if (e.getSource() == materialAmbientBSlider) {
			materialAmbient[2] = materialAmbientBSlider.getValue()/100f;
		}
		else if (e.getSource() == materialDiffuseRSlider) {
			materialDiffuse[0] = materialDiffuseRSlider.getValue()/100f;
		}
		else if (e.getSource() == materialDiffuseGSlider) {
			materialDiffuse[1] = materialDiffuseGSlider.getValue()/100f;
		}
		else if (e.getSource() == materialDiffuseBSlider) {
			materialDiffuse[2] = materialDiffuseBSlider.getValue()/100f;
		}
		else if (e.getSource() == materialSpecularRSlider) {
			materialSpecular[0] = materialSpecularRSlider.getValue()/100f;
		}
		else if (e.getSource() == materialSpecularGSlider) {
			materialSpecular[1] = materialSpecularGSlider.getValue()/100f;
		}
		else if (e.getSource() == materialSpecularBSlider) {
			materialSpecular[2] = materialSpecularBSlider.getValue()/100f;
		}
		else if (e.getSource() == materialShininessSlider) {
			materialShininess = materialShininessSlider.getValue();
		}
	}

	public void display(GLAutoDrawable drawable) {
		update();
		render(drawable);
	}

	private void update() {	
	}

	
	private void render(GLAutoDrawable drawable) {


		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_POSITION, lightPosition, 0);

		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_AMBIENT, lightAmbient, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_DIFFUSE, lightDiffuse, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_SPECULAR, lightSpecular, 0);
		gl.glLightfv(GL2.GL_LIGHT0,  GL2.GL_POSITION, lightPosition, 0);

		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, materialAmbient, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, materialDiffuse, 0);
		gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, materialSpecular, 0);
		gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, materialShininess);

		glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE );

		glu.gluSphere(quad, 5f, 32, 32);	
	}
	
	public void dispose(GLAutoDrawable drawable) {
		// put the cleanup code here
		
	}

	public void init(GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();
		glu = new GLU();
		
		quad = glu.gluNewQuadric();

		gl.glEnable(GL2.GL_DEPTH_TEST);
		
		gl.glEnable(GL2.GL_LIGHTING);
		gl.glEnable(GL2.GL_LIGHT0);
		
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, 1f, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();
		glu.gluLookAt(viewerX, viewerY, viewerZ, 0, 0, 0, 0, 0, 1);
		gl.glClearColor(1f, 1f, 1f, 1f);
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		// this is called when the window is resized
		gl.glViewport(0, 0, width, height);
		float aspect = width*1.0f/height;
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(60f, aspect, 0.5f, 200f); 
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		
		
	}
	
}
